package cn.agrael.struts.plugin.ejb3;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.util.Map;
import java.util.Set;

import cn.agrael.util.CollectionUtils;

import com.opensymphony.xwork2.ActionProxy;

/**
 * ActionProxy 动态代理调用处理程序。
 * 
 * @author <a href="mailto:agraellee@gmail.com">Agrael·Lee</a>
 * 
 */
public class ActionProxyHandler implements InvocationHandler {

	/** 被代理的源对象 */
	private ActionProxy actionProxy;

	/** actionProxy 中的 action 的类级别拦截器注解信息包装器 */
	private InterceptorsAnnotationWrapper classInterceptors;

	/** actionProxy 中的 action 的方法级别拦截器注解信息包装器印射 */
	private Map<String, InterceptorsAnnotationWrapper> methodInterceptors;

	/** 属于 action 中的公共方法 */
	private Set<String> actionMethods;

	/**
	 * 构造一个新的 ActionProxyHandler。
	 * 
	 * @param actionProxy 被代理的源对象。
	 * @param classInterceptors actionProxy 中的 action 的类级别拦截器注解信息包装器。
	 * @param methodInterceptors actionProxy 中的 action 的方法级别拦截器注解信息包装器印射。
	 */
	public ActionProxyHandler(ActionProxy actionProxy, InterceptorsAnnotationWrapper classInterceptors,
			Map<String, InterceptorsAnnotationWrapper> methodInterceptors) {
		this.actionProxy = actionProxy;
		this.classInterceptors = classInterceptors;
		this.methodInterceptors = methodInterceptors;
		this.actionMethods = StrutsEJBUtils.getActionPublicMethodNames(actionProxy.getAction().getClass());
	}

	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		String methodName = method.getName();
		if ((this.classInterceptors != null || !CollectionUtils.isEmpty(this.methodInterceptors))
				&& this.actionMethods.contains(methodName)) {
			// 如果类级别拦截器不为 null 或者方法级别拦截器印射不为空， 且是action中的方法，则执行创建
			return StrutsEJBUtils.createInvocationContext(this.actionProxy, method, args, this.methodInterceptors.get(methodName),
					this.classInterceptors).proceed();
		}
		return method.invoke(this.actionProxy, args);
	}
}
